package com.gridpower.spreadsheet.client.widgets;

import java.util.ArrayList;
import java.util.Iterator;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.widgetideas.graphics.client.Color;
import com.google.gwt.widgetideas.graphics.client.GWTCanvas;
import com.gridpower.spreadsheet.client.models.AppModel;
import com.gridpower.spreadsheet.client.models.DocModel;
import com.gridpower.spreadsheet.client.models.UIMouseModel;
import com.gridpower.spreadsheet.client.models.UISelectModel;
import com.gridpower.spreadsheet.client.models.AppModel.CellSelection;

public class VertRuler {
	int viewableTop = 0; // x, if the seperator has effect
	int height = 600;
	int width = 30;
	int seperatorHeight = 16;
	
	private AbsolutePanel heldPanel = new AbsolutePanel() {
		@Override
		public void onBrowserEvent(Event evt) {
			//System.out.println("widget"+DOM.eventGetType(evt));
			handleBrowserEvent(evt);
		}
	};
	private GWTCanvas gridCanvas = new GWTCanvas();
	private TextLayer txtCanvas = new TextLayer();
	protected GWTCanvas decorateCanvas = new GWTCanvas();
	
	public VertRuler() {
		heldPanel.sinkEvents( DOM.getEventsSunk(heldPanel.getElement())
				|Event.MOUSEEVENTS | Event.ONCLICK);
		heldPanel.setWidth(width+"px");
		heldPanel.add(gridCanvas, 0,0);
		heldPanel.add(txtCanvas, 0, 0);
		heldPanel.add(decorateCanvas, 0, 0);
	}
	public void render() {
		gridCanvas.clear();
		gridCanvas.setGlobalCompositeOperation(GWTCanvas.DESTINATION_OVER);
	    gridCanvas.setLineWidth(1);
	    gridCanvas.setBackgroundColor(Color.LIGHTGREY);
	    gridCanvas.beginPath();
	    gridCanvas.moveTo(0, 0);
	    gridCanvas.lineTo(0, height);
	    gridCanvas.moveTo(width, 0);
	    gridCanvas.lineTo(width, height);
	    DocModel docModel = AppModel.getInstance().getCurrentDoc();
	    int fixed = docModel.getFixedRowCount();
	    ArrayList rowStarts = UIUtil.getAppView().getRowStarts();
	    
	    int i = 0;
	    int y = 0;
	    Iterator itr = rowStarts.iterator();
	    while (itr.hasNext()) {
	    	y = (Integer)itr.next();
	    	++i;
	    	gridCanvas.moveTo(0, y); gridCanvas.lineTo(width, y);
	    	if (i == fixed+1)
	    		break;
	    }
	    int stY = y+seperatorHeight;
	    int base = seperatorHeight-viewableTop;
	    while (itr.hasNext()) {
	    	y = base + (Integer)itr.next();
	    	++i;
	    	if (y >= stY) {
	    		gridCanvas.moveTo(0, y); gridCanvas.lineTo(width, y);
	    	}
	    }
	    gridCanvas.stroke();
		// render the text!
		// render to the fixed
	    //txtCanvas.clear();//todo:bug!
	    txtCanvas.clearElems();
	    // return all the element
		String str = "";
		for (i = 0; i < fixed; ++i) {
			int y1 = (Integer)rowStarts.get(i);
			int x1 = 0;
			int wid = width;
			int hgt = (Integer)rowStarts.get(i+1)-x1;
			Element div = UIUtil.getAppView().getVertRulerTextElement(i);
			str = "";
			str = Integer.toString(i);
			txtCanvas.drawTextInElement(div, x1, y1,
					wid, hgt, str, null, null, "0", null);
			// render the txt
		}
		//int critX = (Integer)rowStarts.get(fixed);
		for (; i < rowStarts.size() - 1; ++i) {
			int y1 = (Integer)rowStarts.get(i) ;
			int x1 = 0;
			int nextY = (Integer)rowStarts.get(i+1);
			int hgt = nextY -y1;
			int wid = width;
			str = "";
			str = Integer.toString(i);
			Element div = UIUtil.getAppView().getVertRulerTextElement(i);
			if (nextY+base >= stY&& y1+base <= height) {
				txtCanvas.drawTextInElement(div, x1, y1+ base,
						wid, hgt, str, null, null, "0", null);
			}
		}
	}
	public void handleBrowserEvent(Event event) {
		UIMouseModel mouseModel = AppModel.getInstance().getMouseModel();

		 switch (DOM.eventGetType(event)) {
	      case Event.ONMOUSEDOWN:
	      {
	    	  Element senderElem = heldPanel.getElement();
	    	  int y = DOM.eventGetClientY(event)
	    	  	- DOM.getAbsoluteTop(senderElem)
	    	  	//+ DOM.getElementPropertyInt(senderElem, "scrollLeft")
	    	  	+ Window.getScrollTop();
	    	  UISelectModel selectModel = AppModel.getInstance().getSelectModel();
	    	  DocModel docModel =AppModel.getInstance().getCurrentDoc();

	    	  ArrayList rowStarts = UIUtil.getAppView().getRowStarts();
	    	  int fixed = docModel.getFixedRowCount();
	    	  if (y > (Integer)rowStarts.get(fixed)) {
	    		y += viewableTop-seperatorHeight;  
	    	  } 
	    	  int row = GridPart.binarySearch(rowStarts, 0, rowStarts.size(), y, 0);
	    	  mouseModel.setObjectMouseDownOn(UIMouseModel.OBJ_VERTRULER);
	    	  mouseModel.setMouseDown(true);
	    	  mouseModel.setDownRow(row);//must
	    	  selectModel.setRowColSelection(true);
	    	  CellSelection sel = selectModel.getCurrentSelect();
	    	  sel.colStart = 0; sel.colEnd =docModel.getColCount()-1;
	    	  sel.rowStart = sel.rowEnd = row;
	    	  
	    	  break;  
	      }
	      case Event.ONMOUSEUP:
	      {
	    	  // set mouse down to false
	    	  mouseModel.setMouseDown(false);

	    	  if (mouseModel.getObjectMouseDownOn().equals(UIMouseModel.OBJ_VERTRULER)) {
	    			  //&& mouseModel.isMouseDown() == true) {
	    		  setCurrentSelect(event);
	    	  }
	    	  break;
	      }
	      case Event.ONMOUSEMOVE:
	      {
	    	  if (mouseModel.getObjectMouseDownOn().equals(UIMouseModel.OBJ_VERTRULER)
	    			  && mouseModel.isMouseDown() == true) {
	    		  setCurrentSelect(event);
	    	  }
	    	  break;
	      }
		 }
	      
	 }
	
	public int getHeight() {
		return height;
	}
	public int getSeperatorHeight() {
		return seperatorHeight;
	}
	public int getViewableLeft() {
		return viewableTop;
	}
	public int getWidth() {
		return width;
	}
	
	public void setHeight(int height) {
		this.height = height;
		heldPanel.setHeight(height+"px");
		gridCanvas.resize(width, height);
		txtCanvas.setSize(Integer.toString(width) + "px",
				Integer.toString(height)+"px");
		//render();
	}
	public void setSeperatorWidth(int seperatorWidth) {
		this.seperatorHeight = seperatorWidth;
	}
	public void setViewableTop(int viewableLeft) {
		this.viewableTop = viewableLeft;
		//render();
	}
	public void setWidth(int width) {
		heldPanel.setWidth(width+"px");
		gridCanvas.resize(width, height);
		txtCanvas.setSize(Integer.toString(width) + "px",
				Integer.toString(height)+"px");
		this.width = width;
	}
	public AbsolutePanel getHeldPanel() {
		return heldPanel;
	}
	public void setHeldPanel(AbsolutePanel heldPanel) {
		this.heldPanel = heldPanel;
	}
	
	private void setCurrentSelect(Event event) {
		UISelectModel selectModel = AppModel.getInstance().getSelectModel();
		DocModel docModel =AppModel.getInstance().getCurrentDoc();
		UIMouseModel mouseModel = AppModel.getInstance().getMouseModel();
		Element senderElem = heldPanel.getElement();
		int y = DOM.eventGetClientY(event)
			- DOM.getAbsoluteTop(senderElem)
			+ Window.getScrollTop();
		ArrayList rowStarts = UIUtil.getAppView().getRowStarts();
		int fixed = docModel.getFixedRowCount();
		if (y > (Integer)rowStarts.get(fixed)) {
			y += viewableTop-seperatorHeight;  
		} 
		int row = GridPart.binarySearch(rowStarts, 0, rowStarts.size(), y, 0);
		CellSelection sel = selectModel.getCurrentSelect();
		sel.colStart = 0; sel.colEnd =docModel.getColCount()-1;
		sel.rowStart = mouseModel.getDownRow(); sel.rowEnd = row;
		sel.normalize();
		selectModel.fireModelChange();
	}
}
